<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2014 Yury Kharlamov

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Generated Inversion-Of-Control container
https://code.google.com/p/gen-ioc/

* * *

This transformaation generates base classes with setters/getters
and factories for IOC container
-->
<xsl:stylesheet 
    version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:fn="http://www.w3.org/2005/xpath-functions"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:my="http://www.yyk.ru/build"
    >

    <xsl:output method="text"/>

    <xsl:param name="OutDir" select="''"/>
    <xsl:param name="BaseIncludeDir" select="''"/>

    <xsl:template match="root">
        <xsl:variable name="classes">
            <xsl:call-template name="LoadDeps"/>
        </xsl:variable>
        <xsl:call-template name="GenClasses">
            <xsl:with-param name="classes" select="$classes/class"/>
            <xsl:with-param name="allEmitted" select="'IObjectManager'"/>
            <xsl:with-param name="allEmittedSingletons" select="'IObjectManager'"/>
            <xsl:with-param name="createdClasses" select="()"/>
        </xsl:call-template>
        <xsl:call-template name="GenFactories">
            <xsl:with-param name="classes" select="$classes/class"/>
        </xsl:call-template>
        <xsl:call-template name="GenIfaceIds">
            <xsl:with-param name="classes" select="$classes/class"/>
        </xsl:call-template>
    </xsl:template>
    
    <xsl:template name="LoadDeps">
        <xsl:param name="gen" select="fn:true()"/>
        <xsl:for-each select="include">
            <xsl:variable name="subDoc">
                <xsl:copy-of select="document(fn:concat('file:/',$BaseIncludeDir,'/',@file))//(include|class)"/>
            </xsl:variable>
            <xsl:for-each select="$subDoc">
                <xsl:call-template name="LoadDeps">
                    <xsl:with-param name="gen" select="fn:false()"/>
        </xsl:call-template>
            </xsl:for-each>
        </xsl:for-each>
        <xsl:for-each select="class">
            <xsl:element name="class" xmlns="">
                <xsl:for-each select="@*">
                    <xsl:copy-of select="."/>
                </xsl:for-each>
                <xsl:attribute name="gen" select="$gen"/>
            </xsl:element>
            <xsl:message>
                class name: <xsl:value-of select="@name"/>, gen: <xsl:value-of select="$gen"/>
            
            </xsl:message>
        </xsl:for-each>
    </xsl:template>


    <xsl:template name="GenClasses">
        <xsl:param name="classes"/>
        <xsl:param name="allEmitted"/>
        <xsl:param name="allEmittedSingletons"/>
        <xsl:param name="createdClasses"/>
        <xsl:if test="fn:count($classes) > 0">
            <xsl:variable name="class" select="$classes[1]"/>
            <xsl:if test="$class/@gen eq 'true'">
            <xsl:text>Generating </xsl:text><xsl:value-of select="$class/@name"/><xsl:text> ...&#x0a;</xsl:text>
            <xsl:call-template name="GenClass">
                <xsl:with-param name="classNode" select="$class"/>
                <xsl:with-param name="allEmitted" select="$allEmitted"/>
                <xsl:with-param name="allEmittedSingletons" select="$allEmittedSingletons"/>
                <xsl:with-param name="createdClasses" select="$createdClasses"/>
            </xsl:call-template>
            </xsl:if>
            <xsl:if test="$class/@gen ne 'true'">
                <xsl:text>Parsing </xsl:text><xsl:value-of select="$class/@name"/><xsl:text> ...&#x0a;</xsl:text>
            </xsl:if>
            <xsl:variable name="emittedIfaces" select="my:getIfacesNoEvents($class/@emits)"/>
            <xsl:variable name="consumedIfaces" select="my:getIfacesNoEvents($class/@consumes)"/>
            <xsl:call-template name="TestAllIfacesAreDeclared">
                <xsl:with-param name="consumes" select="$consumedIfaces"/>
                <xsl:with-param name="allEmitted" select="$allEmitted"/>
            </xsl:call-template>
            <xsl:variable name="allEmittedNew" select="$allEmitted, $emittedIfaces, $class/@name"/>
            <xsl:variable name="allEmittedSingletonsNew" select="my:If($class/@singleton, ($allEmittedSingletons, $emittedIfaces, $class/@name), $allEmittedSingletons)"/>
            <xsl:variable name="createdClassesNew">
                <xsl:copy-of select="$createdClasses"/>
                <xsl:element name="class">
                    <xsl:attribute name="name" select="$class/@name"/>
                    <xsl:attribute name="singleton" select="$class/@singleton"/>
                    <xsl:if test="fn:count($emittedIfaces) gt 0">
                        <xsl:attribute name="defaultIface" select="$emittedIfaces[1]"/>
                    </xsl:if>
                </xsl:element>
            </xsl:variable>
            <xsl:if test="fn:count($classes)>1">
                <xsl:variable name="left" select="$classes[fn:position()>1]"/>
                <xsl:call-template name="GenClasses">
                    <xsl:with-param name="classes" select="$left"/>
                    <xsl:with-param name="allEmitted" select="$allEmittedNew"/>
                    <xsl:with-param name="allEmittedSingletons" select="$allEmittedSingletonsNew"/>
                    <xsl:with-param name="createdClasses" select="$createdClassesNew"/>
                </xsl:call-template>
            </xsl:if>
            <xsl:if test="fn:count($classes) eq 1">
                <xsl:for-each select="$createdClassesNew/class">
                    Name: <xsl:value-of select="@name"/><xsl:text>&#x0a;</xsl:text>
                    Def iface: <xsl:value-of select="@defaultIface"/><xsl:text>&#x0a;</xsl:text>
                </xsl:for-each>
            </xsl:if>
                
        </xsl:if>
    </xsl:template>

    <xsl:template name="GenClass">
        <xsl:param name="classNode"/>
        <xsl:param name="allEmitted"/>
        <xsl:param name="allEmittedSingletons"/>
        <xsl:param name="createdClasses"/>
        <xsl:for-each select="$classNode">
            <xsl:variable name="baseClassName" select="fn:concat(@name, 'Base')"/>
            <xsl:variable name="result">
                /* This file is AUTO GENERATED by gen-ioc. */
                /* Contains base class for <xsl:value-of select="."/> */
                <xsl:variable name="emits" select="my:splitIds(@emits)"/>
                <xsl:variable name="consumes" select="my:splitIds(@consumes)"/>
                <xsl:for-each select="$consumes">
                    <xsl:if test="my:IsClass(., $createdClasses)">
                        struct <xsl:value-of select="."/>Class;
                    </xsl:if>
                </xsl:for-each>
                class <xsl:value-of select="$baseClassName"/>
                <xsl:variable name="needSetters" select="my:NeedSetters($emits,$consumes)" as="xs:boolean"/>
                <xsl:variable name="shutdown" select="my:If(fn:empty(@shutdown), fn:false(), @shutdown)" as="xs:boolean"/>
                <xsl:variable name="inherited" 
                    select="my:getInheritedIfaces($emits,$consumes,$shutdown,$needSetters)"/>
                <xsl:call-template name="AddInherited">
                    <xsl:with-param name="inherited" select="$inherited"/>
                </xsl:call-template>
                <xsl:text>&#x0a;{&#x0a;</xsl:text>
                protected:
                struct _Unique{};
                private:
                <xsl:if test="$needSetters">
                    <xsl:call-template name="GenSetters">
                        <xsl:with-param name="emits" select="$emits"/>
                        <xsl:with-param name="consumes" select="$consumes"/>
                        <xsl:with-param name="allEmittedSingletons" select="$allEmittedSingletons"/>
                        <xsl:with-param name="createdClasses" select="$createdClasses"/>
                    </xsl:call-template>
                </xsl:if>
                <xsl:call-template name="GenAccessors">
                    <xsl:with-param name="consumes" select="$consumes"/>
                    <xsl:with-param name="allEmittedSingletons" select="$allEmittedSingletons"/>
                    <xsl:with-param name="createdClasses" select="$createdClasses"/>
                </xsl:call-template>
                <xsl:text>&#x0a;};&#x0a;</xsl:text>
                <xsl:call-template name="AddFactoryProto">
                    <xsl:with-param name="className" select="@name"/>
                </xsl:call-template>
            </xsl:variable>
            <xsl:call-template name="SaveToFileIfChanged">
                <xsl:with-param name="fileName" select="fn:concat($baseClassName, '.h')"/>
                <xsl:with-param name="text" select="$result"/>
            </xsl:call-template>
        </xsl:for-each>
    </xsl:template>

    <xsl:template name="GenIfaceIds">
        <xsl:param name="classes"/>
        <xsl:variable name="result">
            /* This file is AUTO GENERATED by gen-ioc. */
            /* Contains type id objects for interfaces and classes. */
            <xsl:variable name="allClassIds" select="fn:distinct-values($classes/@name)"/>
            <xsl:variable name="allIfaceIds" select="fn:distinct-values((my:getIfacesNoEvents($classes/@emits), my:getIfacesNoEvents($classes/@consumes)))"/>
            <xsl:for-each select="$allClassIds">
                struct <xsl:value-of select="."/>Class{};
                template&lt;&gt;
                IfaceId GetTypeId&lt;<xsl:value-of select="."/>Class&gt;(){ return "<xsl:value-of select="."/>"; }
            </xsl:for-each>
            <xsl:for-each select="$allIfaceIds">
                struct <xsl:value-of select="."/>;
                template&lt;&gt;
                IfaceId GetTypeId&lt;<xsl:value-of select="."/>&gt;(){ return "<xsl:value-of select="."/>"; }
            </xsl:for-each>
        </xsl:variable>
        <xsl:call-template name="SaveToFileIfChanged">
            <xsl:with-param name="fileName" select="'IfaceIds.h'"/>
            <xsl:with-param name="text" select="$result"/>
        </xsl:call-template>
    </xsl:template>

    <xsl:template name="GenIfaceIdsDecls">
        <xsl:param name="classes"/>
        <xsl:variable name="allClassIds" select="fn:distinct-values($classes/@name)"/>
        <xsl:variable name="allIfaceIds" select="fn:distinct-values((my:getIfacesNoEvents($classes/@emits), my:getIfacesNoEvents($classes/@consumes)))"/>
        <xsl:for-each select="$allClassIds">
            struct <xsl:value-of select="."/>Class; 
        </xsl:for-each>
        <xsl:for-each select="$allIfaceIds">
            struct <xsl:value-of select="."/>;
        </xsl:for-each>
        struct IEventDispatcher;
    </xsl:template>

    <xsl:template name="GenFactories">
        <xsl:param name="classes"/>
        <xsl:variable name="result">
            /* This file is AUTO GENERATED by gen-ioc. */
            /* Contains factory objects for each class. */
            <xsl:call-template name="GenIfaceIdsDecls">
                <xsl:with-param name="classes" select="$classes"/>
            </xsl:call-template>
            <xsl:for-each select="$classes">
                <xsl:call-template name="AddFactoryProto">
                    <xsl:with-param name="className" select="@name"/>
                </xsl:call-template>
                <xsl:variable name="emits" select="my:splitIds(@emits)"/>
                <xsl:variable name="consumes" select="my:splitIds(@consumes)"/>

                namespace factory
                {
                    class <xsl:value-of select="@name"/> : public IFactory
                    {
                    public:
                        void Add(IObjectManager&amp; man) override
                        {
                        IfaceIdList consumes, emits;
                        <xsl:for-each select="$consumes">
                            <xsl:if test=". ne 'events'">
                                <xsl:variable name="id" select="."/>
                                <xsl:variable name="typeId" select="my:If(fn:exists($classes[@name eq $id]), fn:concat(.,'Class'), .)"/>
                                consumes.push_back(ID_OF(<xsl:value-of select="$typeId"/>));
                            </xsl:if>
                        </xsl:for-each>
                        <xsl:for-each select="$emits">
                            <xsl:if test=". ne 'events'">
                                emits.push_back(ID_OF(<xsl:value-of select="."/>));
                            </xsl:if>
                            <xsl:if test=". eq 'events'">
                                consumes.push_back(ID_OF(IEventDispatcher));
                            </xsl:if>
                        </xsl:for-each>
                        man.AddFactory(&amp;Create<xsl:value-of select="@name"/>, ID_OF(<xsl:value-of select="@name"/>Class), consumes, emits, <xsl:value-of select="@singleton"/>);
                        }
                    };
                };
            </xsl:for-each>
            namespace factory
            {
                inline void AddAllFactories(IObjectManager&amp; man)
                {
                <xsl:for-each select="$classes">
                    <xsl:value-of select="@name"/>().Add(man);
                </xsl:for-each>
                }
            }
        </xsl:variable>
        <xsl:call-template name="SaveToFileIfChanged">
            <xsl:with-param name="fileName" select="'Factories.h'"/>
            <xsl:with-param name="text" select="$result"/>
        </xsl:call-template>
    </xsl:template>

    <xsl:template name="AddFactoryProto">
        <xsl:param name="className"/>
        std::shared_ptr&lt;IObject&gt; Create<xsl:value-of select="$className"/>();
    </xsl:template>

    <xsl:template name="TestAllIfacesAreDeclared">
        <xsl:param name="consumes"/>
        <xsl:param name="allEmitted"/>
        <xsl:for-each select="$consumes">
            <xsl:if test=". ne 'events' and fn:not(my:Contains($allEmitted, .))">
                <xsl:message terminate="yes">
                    Interface not implemented: <xsl:value-of select="."/>
                </xsl:message>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>
    
    <xsl:template name="GenSetters">
        <xsl:param name="emits"/>
        <xsl:param name="consumes"/>
        <xsl:param name="allEmittedSingletons"/>
        <xsl:param name="createdClasses"/>
	    template &lt; class T &gt;
	    std::shared_ptr&lt;T&gt; Create();
        void SetIfaceFactory(const IfaceId &amp; ifaceId, const Factory &amp; factory) override
        {
        <xsl:if test="my:Contains($emits,'events')">
            if (ifaceId == ID_OF(IEventDispatcher))
                SetDispatcherFactory(factory);
        </xsl:if>
        <xsl:for-each select="$consumes">
            <xsl:if test=". ne 'events'">
                <xsl:variable name="class" select="my:GetClass(., $createdClasses)"/>
                <xsl:variable name="isClass" select="fn:exists($class)" as="xs:boolean"/>
                <xsl:variable name="isSingleton" select="my:If($isClass, $class/@singleton, my:Contains($allEmittedSingletons, .))" as="xs:boolean"/>
                <xsl:variable name="typeId" select="my:If($isClass, fn:concat(.,'Class'), .)"/>
                if (ifaceId == ID_OF(<xsl:value-of select="$typeId"/>))
                <xsl:if test="$isSingleton">
                    m_<xsl:value-of select="."/>.Set(factory);
                </xsl:if>
                <xsl:if test="fn:not($isSingleton)">
                    m_<xsl:value-of select="."/>Factory = factory;
                </xsl:if>
            </xsl:if>
        </xsl:for-each>
        }
    </xsl:template>
    
    <xsl:template name="GenAccessors">
        <xsl:param name="consumes"/>
        <xsl:param name="allEmittedSingletons"/>
        <xsl:param name="createdClasses"/>
        <xsl:for-each select="$consumes">
            <xsl:if test=". ne 'events'">
                <xsl:variable name="class" select="my:GetClass(., $createdClasses)"/>
                <xsl:variable name="isClass" select="fn:exists($class)" as="xs:boolean"/>
                <xsl:variable name="isSingleton" select="my:If($isClass, xs:boolean($class/@singleton), my:Contains($allEmittedSingletons, .))" as="xs:boolean"/>
                <xsl:variable name="targetIface" select="my:If($isClass, $class/@defaultIface, .)"/>
                
                <xsl:if test="$isSingleton">
                    protected:
                    LazyPtr&lt;<xsl:value-of select="$targetIface"/>&gt; m_<xsl:value-of select="."/>;
                </xsl:if>
                <xsl:if test="fn:not($isSingleton)">
                    private:
                    Factory m_<xsl:value-of select="."/>Factory;

                    protected:
                    typedef private_ptr&lt;<xsl:value-of select="$targetIface"/>,_Unique&gt; <xsl:value-of select="$targetIface"/>Ptr;
                    <xsl:value-of select="$targetIface"/>Ptr
                Create_<xsl:value-of select="."/>()
                    {
                        return std::dynamic_pointer_cast&lt;<xsl:value-of select="$targetIface"/>&gt;(m_<xsl:value-of select="."/>Factory());
                    }
                </xsl:if>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>
        
    <xsl:function name="my:If">
        <xsl:param name="condition" as="xs:boolean"/>
        <xsl:param name="ifTrueValue"/>
        <xsl:param name="ifFalseValue"/>
        <xsl:if test="$condition">
            <xsl:copy-of select="$ifTrueValue"/>
        </xsl:if>
        <xsl:if test="fn:not($condition)">
            <xsl:copy-of select="$ifFalseValue"/>
        </xsl:if>
    </xsl:function>

    <xsl:function name="my:Contains" as="xs:boolean">
        <xsl:param name="sequence"/>
        <xsl:param name="item"/>
        <xsl:copy-of select="fn:not(fn:empty(fn:index-of($sequence,$item)))"/>
    </xsl:function>
    
    <xsl:template name="SaveToFileIfChanged">
        <xsl:param name="fileName"/>
        <xsl:param name="text"/>
        <xsl:variable name="dir" select="my:If(fn:substring($OutDir, fn:string-length($OutDir)) eq '\', $OutDir, fn:concat($OutDir,'\'))"/>
        <xsl:variable name="path" select="fn:concat($dir,$fileName)"/>
        <xsl:variable name="normPath" select="fn:replace($path, '\\', '/')"/>
        <xsl:variable name="uriPath" select="fn:concat('file:///', $normPath)"/>
        <!--xsl:call-template name="my:CompareWithFile">
            <xsl:with-param name="fileName" select="$uriPath"/>
            <xsl:with-param name="text" select="$text"/>
        </xsl:call-template-->
        
        <xsl:variable name="need" select="my:IsNeedToUpdate($uriPath, $text)" as="xs:boolean"/>
        <xsl:text/>Need to update '<xsl:value-of select="$path"/>':<xsl:value-of select="$need"/><xsl:text>&#x0a;</xsl:text>
        <xsl:if test="$need">
            <xsl:result-document href="{$uriPath}" method="text">
                <xsl:value-of select="$text"/>
            </xsl:result-document>
            <xsl:text>Updated </xsl:text>
            <xsl:value-of select="$uriPath"/>
            <xsl:text>&#x0a;</xsl:text>
        </xsl:if>
    </xsl:template>


    <!--xsl:template name="my:CompareWithFile">
        <xsl:param name="fileName"/>
        <xsl:param name="text"/>
        <xsl:variable name="isFileExists" select="unparsed-text-available($fileName)" as="xs:boolean"/>
        File <xsl:value-of select="$fileName"/> exists: <xsl:value-of select="$isFileExists"/>
        <xsl:if test="$isFileExists">
            <xsl:variable name="oldText" select="fn:replace(unparsed-text($fileName),'&#x0d;&#x0a;','&#x0a;')"/>
            <xsl:variable name="newText" select="fn:replace($text,'&#x0d;&#x0a;','&#x0a;')"/>
            Old:<xsl:value-of select="fn:string-length($oldText)"/>
            New:<xsl:value-of select="fn:string-length($newText)"/>
        </xsl:if>
        <xsl:if test="fn:not($isFileExists)">
            Not Exists
        </xsl:if>
    </xsl:template-->

    <xsl:function name="my:IsNeedToUpdate" as="xs:boolean">
        <xsl:param name="fileName"/>
        <xsl:param name="text"/>
        <xsl:variable name="isFileExists" select="unparsed-text-available($fileName)" as="xs:boolean"/>
        <xsl:if test="$isFileExists">
            <xsl:variable name="oldText" select="fn:replace(unparsed-text($fileName),'&#x0d;&#x0a;','&#x0a;')"/>
            <xsl:copy-of select="$text ne $oldText"/>
        </xsl:if>
        <xsl:if test="fn:not($isFileExists)">
            <xsl:copy-of select="fn:true()"/>
        </xsl:if>
    </xsl:function>

    <xsl:function name="my:getIfacesNoEvents">
        <xsl:param name="commaSeparatedValues" as="xs:string*"/>
        <xsl:for-each select="$commaSeparatedValues">
            <xsl:variable name="values" select="my:splitIds(.)"/>
            <xsl:for-each select="$values">
                <xsl:if test=". ne 'events'">
                    <xsl:copy-of select="."/>
                </xsl:if>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:function>
    
    <xsl:function name="my:getInheritedIfaces">
        <xsl:param name="emits"/>
        <xsl:param name="consumes"/>
        <xsl:param name="shutdown" as="xs:boolean"/>
        <xsl:param name="needSetters" as="xs:boolean"/>
        
        <xsl:for-each select="$emits">
            <xsl:if test=". eq 'events'">
                <xsl:text>EventSource</xsl:text>
            </xsl:if>
            <xsl:if test=". ne 'events'">
                <xsl:copy-of select="."/>
            </xsl:if>
        </xsl:for-each>
        <xsl:if test="my:Contains($consumes, 'events')">
            <xsl:text>IEventQueue</xsl:text>
        </xsl:if>
        <xsl:if test="$shutdown">
            <xsl:text>IShutdown</xsl:text>
        </xsl:if>
        <xsl:if test="$needSetters">
            <xsl:text>ISetters</xsl:text>
        </xsl:if>
    </xsl:function>

    <xsl:function name="my:splitIds">
        <xsl:param name="commaSeparatedValues" as="xs:string*"/>
        <xsl:for-each select="$commaSeparatedValues">
            <xsl:for-each select="fn:tokenize(.,',')">
                <xsl:value-of select="fn:normalize-space(.)"/>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:function>

    <xsl:function name="my:NeedSetters" as="xs:boolean">
        <xsl:param name="emits"/>
        <xsl:param name="consumes"/>
        <xsl:variable name="emitsHasEvents" select="my:Contains($emits, 'events')" as="xs:boolean"/>
        <xsl:if test="$emitsHasEvents">true</xsl:if>
        <xsl:if test="fn:not($emitsHasEvents)">
            <xsl:variable name="consumesMoreThan1" select="fn:count($consumes) gt 1" as="xs:boolean"/>
            <xsl:if test="$consumesMoreThan1">true</xsl:if>
            <xsl:if test="fn:not($consumesMoreThan1)">
                <xsl:if test="fn:empty($consumes)">false</xsl:if>
                <xsl:if test="fn:not(fn:empty($consumes))">
                    <xsl:copy-of select="fn:not(my:Contains($consumes, 'events'))"/>
                </xsl:if>
            </xsl:if>
        </xsl:if>
    </xsl:function>

    <xsl:template name="AddInherited">
        <xsl:param name="inherited"/>
        <xsl:if test="fn:count($inherited)>0">
            <xsl:text>:</xsl:text>
            <xsl:for-each select="$inherited">
                <xsl:text> public </xsl:text>
                <xsl:value-of select="fn:string()"/>
                <xsl:if test="fn:position() lt fn:count($inherited)">, </xsl:if>
            </xsl:for-each>
        </xsl:if>
    </xsl:template>
    
    <xsl:function name="my:GetClass">
        <xsl:param name="id" as="xs:string"/>
        <xsl:param name="createdClasses"/>
        <xsl:copy-of select="$createdClasses/class[@name eq $id]"/>
    </xsl:function>
        
    <xsl:function name="my:IsClass">
        <xsl:param name="id" as="xs:string"/>
        <xsl:param name="createdClasses"/>
        <xsl:copy-of select="fn:exists($createdClasses/class[@name eq $id])"/>
    </xsl:function>
    
    <xsl:function name="my:IsClassSingleton" as="xs:boolean">
        <xsl:param name="id" as="xs:string"/>
        <xsl:param name="createdClasses"/>
        <xsl:variable name="class" select="$createdClasses/class[@name eq $id]"/>
        <xsl:if test="fn:exists($class)">
            <xsl:copy-of select="$class/@singleton"/>
        </xsl:if>
         <xsl:if test="fn:not(fn:exists($class))">
            <xsl:copy-of select="fn:false()"/>
        </xsl:if>
    </xsl:function>
    
</xsl:stylesheet>
